package com.caption.core.executor;

import com.caption.entity.WorkExecutor;
import com.caption.mapper.WorkExecutorMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.concurrent.*;

/**
 * 线程池工厂
 */
@Component
@Slf4j
public class WorkExecutorFactory {
    @Autowired
    private WorkExecutorMapper workExecutorMapper;

    private static WorkExecutorRepository repository = WorkExecutorRepository.getInstance();

    @PostConstruct
    public void init() throws Exception {
        List<WorkExecutor> workExecutorList = workExecutorMapper.findAllList();
        for (WorkExecutor config : workExecutorList) {
            repository.bind(config.getExecutorName(), createThreadPool(config));
        }
        log.info("**********初始化完成加载线程池**********");
    }

    public static  ExecutorService getWorkExecutor(String workExecutorName){
        return repository.lookup(workExecutorName);
    }

    public ThreadPoolExecutor createThreadPool(WorkExecutor config) throws Exception{
        if (config.getCorePoolSize() <= 0) {
            throw new RuntimeException("核心线程数配置需要大于0");
        }

        ThreadPoolExecutor threadPoolExecutor = null;
        //有界队列线程池,推荐配置
        if (config.getMaxQueueSize() > 0) {
            threadPoolExecutor = new ThreadPoolExecutor(config.getCorePoolSize(),
                    config.getMaxPoolSize(),config.getKeepAliveTime(), TimeUnit.SECONDS,
                    new ArrayBlockingQueue<>(config.getMaxQueueSize()));
        }else if(config.getMaxQueueSize()==0){
            //没有队列线程池
            threadPoolExecutor = new ThreadPoolExecutor(config.getCorePoolSize(),
                    config.getMaxPoolSize(),config.getKeepAliveTime(),
                    TimeUnit.SECONDS,new SynchronousQueue<>());
        }else {
            //无界队列,不建议配置容易发生OOM
            threadPoolExecutor = new ThreadPoolExecutor(config.getCorePoolSize(),
                    0,0,
                    TimeUnit.SECONDS,new LinkedBlockingDeque<>());
        }
        return threadPoolExecutor;

    }

}
